import Vue from 'vue';
import nodeFilter from 'src/utils/nodeFilter.js';
import {uuid} from 'src/utils/uuid.js';
import tools from 'src/utils/tools.js';
const ATOM_TYPE_DICT = {
  startpoint: 'EmptyStartEvent',
  endpoint: 'EmptyEndEvent',
  tasknode: 'ServiceActivity',
  subflow: 'SubProcess',
  parallelgateway: 'ParallelGateway',
  branchgateway: 'ExclusiveGateway',
  convergegateway: 'ConvergeGateway'
};
// 默认流程模板，默认节点

function generateInitLocation () {
  return [
    {
      id: 'node' + uuid(),
      x: 80,
      y: 150,
      type: 'startpoint'
    },
    {
      id: 'node' + uuid(),
      x: 300,
      y: 135,
      name: '',
      stage_name: window.gettext('步骤1'),
      type: 'tasknode'
    },
    {
      id: 'node' + uuid(),
      x: 600,
      y: 150,
      type: 'endpoint'
    }
  ];
}
// 默认流程模板，activities 字段
function generateInitActivities (location, line) {
  return {
    [location[1].id]: {
      component: {
        code: undefined,
        data: undefined
      },
      error_ignorable: false,
      id: location[1].id,
      incoming: line[0].id,
      loop: null,
      name: '',
      optional: false,
      outgoing: line[1].id,
      stage_name: window.gettext('步骤1'),
      type: 'ServiceActivity',
      can_retry: true,
      isSkipped: true
    }
  };
}
// 默认流程模板，开始节点
function generateStartNode (location, line) {
  return {
    id: location.id,
    incoming: '',
    name: '',
    outgoing: line.id,
    type: 'EmptyStartEvent'
  };
}
// 默认流程模板，结束节点
function generateEndNode (location, line) {
  return {
    id: location.id,
    incoming: line.id,
    name: '',
    outgoing: '',
    type: 'EmptyEndEvent'
  };
}
// 默认流程模板，初始化 line 字段
function generateInitLine (location) {
  const line = [];
  const locationLength = location.length;

  if (locationLength < 2) {
    return line;
  }

  location.forEach((item, index) => {
    if (index > locationLength - 2) {
      return;
    }
    line.push({
      id: 'line' + uuid(),
      source: {
        arrow: 'Right',
        id: item.id
      },
      target: {
        arrow: 'Left',
        id: location[index + 1].id
      }
    });
  });
  return line;
}
// 默认流程模板，初始化 flows 字段
function generateInitFlow (line) {
  const flow = {};

  line.forEach(item => {
    flow[item.id] = {
      id: item.id,
      is_default: false,
      source: item.source.id,
      target: item.target.id
    };
  });
  return flow;
}

const template = {
  namespaced: true,
  state: {
    name: '',
    activities: {},
    end_event: {},
    flows: {},
    gateways: {},
    line: [],
    location: [],
    outputs: [],
    start_event: {},
    template_id: '',
    constants: {},
    businessBaseInfo: {},
    notify_receivers: {
      receiver_group: [],
      more_receiver: ''
    },
    notify_type: [],
    time_out: '',
    category: '',
    subprocess_info: {}
  },
  mutations: {
    setTemplateName (state, name) {
      state.name = name;
    },
    setReceiversGroup (state, data) {
      state.notify_receivers.receiver_group = data;
    },
    setNotifyType (state, data) {
      state.notify_type = data;
    },
    setOvertime (state, data) {
      state.time_out = data;
    },
    setCategory (state, data) {
      state.category = data;
    },
    setSubprocessUpdated (state, subflow) {
      state.subprocess_info.details.some(item => {
        if (
                    subflow.template_id === item.template_id &&
                    subflow.subprocess_node_id === item.subprocess_node_id
                ) {
          item.expired = false;
          subflow.version && (item.version = subflow.version);
          return true;
        }
      });
    },
        // 更新模板各相关字段数据
    setTemplateData (state, data) {
      const {name, template_id, pipeline_tree, notify_receivers,
                notify_type, time_out, category, subprocess_info
            } = data;
      const pipelineTreeOrder = [
        'activities', 'constants', 'end_event', 'flows', 'gateways',
        'line', 'location', 'outputs', 'start_event'
      ];
      const pipelineData = JSON.parse(pipeline_tree);
      const receiver = JSON.parse(notify_receivers);

      state.name = name;
      state.template_id = template_id;
      state.notify_receivers.receiver_group = receiver.receiver_group || [];
      state.notify_type = notify_type ? JSON.parse(notify_type) : [];
      state.time_out = time_out;
      state.category = category;
      state.subprocess_info = subprocess_info;

      pipelineTreeOrder.forEach(key => {
        let val = pipelineData[key];

        if (key !== 'constants') {
          val = nodeFilter.convertInvalidIdData(key, val); // convert old invalid data =_=!
        }
        if (key === 'location') {
          val = val.map(item => {
            if (item.type === 'tasknode' || item.type === 'subflow') {
              const node = state.activities[item.id];
              const loc = Object.assign({}, item, {
                name: node.name,
                stage_name: node.stage_name,
                optional: node.optional,
                error_ignorable: node.error_ignorable,
                can_retry: node.can_retry,
                isSkipped: node.isSkipped
              });

              return loc;
            }
            return item;
          });
        }
        state[key] = val;
      });
    },
    setBusinessBaseInfo (state, data) {
      state.businessBaseInfo = data;
    },
        // 初始化模板数据
    initTemplateData (state) {
      const location = generateInitLocation();
      const line = generateInitLine(location);
      const flow = generateInitFlow(line);
      const activities = generateInitActivities(location, line);
      const start_event = generateStartNode(location[0], line[0]);
      const end_event = generateEndNode(location[2], line[1]);

      state.name = '';
      state.activities = activities;
      state.end_event = end_event;
      state.flows = flow;
      state.gateways = {};
      state.line = line;
      state.location = location;
      state.outputs = [];
      state.start_event = start_event;
      state.template_id = '';
      state.constants = {};
      state.category = '';
    },
        // 重置模板数据
    resetTemplateData (state) {
      state.name = '';
      state.activities = {};
      state.end_event = {};
      state.flows = {};
      state.gateways = {};
      state.line = [];
      state.location = [];
      state.outputs = [];
      state.start_event = {};
      state.template_id = '';
      state.constants = {};
      state.notify_type = [];
      state.notify_receivers = {
        receiver_group: [],
        more_receiver: ''
      };
    },
        // 增加全局变量
    addVariable (state, variable) {
      Vue.set(state.constants, variable.key, variable);
    },
        // 编辑全局变量
    editVariable (state, payload) {
      const {key, variable} = payload;

      Vue.delete(state.constants, key);
      Vue.set(state.constants, variable.key, variable);
    },
        // 删除全局变量
    deleteVariable (state, key) {
      const constant = state.constants[key];
      const {source_info} = constant;

      for (const id in source_info) {
        if (state.activities[id]) {
          source_info[id].forEach(item => {
            let data;

            if (state.activities[id].type === 'ServiceActivity') {
              data = state.activities[id].component.data[item];
            } else {
              const variableKey = /^\$\{[\w]*\}$/.test(item) ? item : '${' + item + '}';

              data = state.activities[id].constants[variableKey];
            }
            if (data) {
              data.hook = false;
              data.value = constant.value;
            }
          });
        }
      }
      const vIndex = state.outputs.indexOf(key);

      vIndex > -1 && state.outputs.splice(vIndex, 1);
      Vue.delete(state.constants, key);
    },
        // 配置全局变量 source_info 字段
    setVariableSourceInfo (state, payload) {
      const {type, id, key, tagCode} = payload;
      const constant = state.constants[key];

      if (!constant) return;
      const sourceInfo = constant.source_info;

      if (type === 'add') {
        if (sourceInfo[id]) {
          sourceInfo[id].push(tagCode);
        } else {
          Vue.set(sourceInfo, id, [tagCode]);
        }
      } else if (type === 'delete') {
        if (sourceInfo[id].length <= 1) {
          Vue.delete(sourceInfo, id);
        } else {
          let atomIndex;

          sourceInfo[id].some((item, index) => {
            if (item === tagCode) {
              atomIndex = index;
              return true;
            }
          });
          sourceInfo[id].splice(atomIndex, 1);
        }
      }
    },
        // 配置分支网关条件
    setBranchCondition (state, condition) {
      const {id, nodeId, name} = condition;

      state.gateways[nodeId]['conditions'][id].evaluate = name;
    },
        // 节点增加、删除、编辑操作，数据更新
    setLocation (state, payload) {
      const {type, location} = payload;
      let locationIndex;
      const isLocationExist = state.location.some((item, index) => {
        if (item.id === location.id) {
          locationIndex = index;
          return true;
        }
      });

      if (type === 'add' && !isLocationExist) {
        const loc = tools.deepClone(location);

        delete loc.atomId; // 添加节点后删除标准插件类型字段
        state.location.push(loc);
      } else {
        if (type === 'edit') {
          state.location.splice(locationIndex, 1, location);
        } else if (type === 'delete') {
          state.location.splice(locationIndex, 1);
        }
      }
    },
        // 节点拖动，位置更新
    setLocationXY (state, location) {
      const {id, x, y} = location;

      state.location.some(item => {
        if (item.id === id) {
          item.x = x;
          item.y = y;
          return true;
        }
      });
    },
        // 增加、删除节点连线操作，更新模板各相关字段数据
    setLine (state, payload) {
      const {type, line} = payload;
      const isLineExist = state.line.some((item, index) => {
        if (
                    item.source.id === line.source.id &&
                    item.target.id === line.target.id
                ) {
          return true;
        }
      });

      if (type === 'add' && !isLineExist) {
        const id = 'line' + uuid();
        const newLine = Object.assign({}, line, {id});
        const sourceNode = newLine.source.id;
        const targetNode = newLine.target.id;

        state.activities[sourceNode] && (state.activities[sourceNode].outgoing = id);
        state.activities[targetNode] && (state.activities[targetNode].incoming = id);
        state.flows[id] = {
          id,
          is_default: false,
          source: sourceNode,
          target: targetNode
        };
        state.start_event.id === sourceNode && (state.start_event.outgoing = id);
        state.end_event.id === targetNode && (state.end_event.incoming = id);
        if (state.gateways[sourceNode]) {
          const gatewayNode = state.gateways[sourceNode];

          if (Array.isArray(gatewayNode.outgoing)) {
            gatewayNode.outgoing.push(id);
            if (gatewayNode.type === ATOM_TYPE_DICT['branchgateway']) {
              const conditions = gatewayNode.conditions;
              const conditionItem = {
                evaluate: Object.keys(conditions).length ? '1 == 0' : '1 == 1',
                tag: `branch_${sourceNode}_${targetNode}`
              };

              Vue.set(conditions, id, conditionItem);
            }
          } else {
            gatewayNode.outgoing = id;
          }
        }
        if (state.gateways[targetNode]) {
          const gatewayNode = state.gateways[targetNode];

          if (Array.isArray(gatewayNode.incoming)) {
            gatewayNode.incoming.push(id);
          } else {
            gatewayNode.incoming = id;
          }
        }
        state.line.push(newLine);
      } else if (type === 'delete') { // async activities、flows、gateways、start_event、end_event
        let deletedLine;

        for (const item in state.flows) {
          const flow = state.flows[item];

          if (flow.source === line.source.id && flow.target === line.target.id) {
            deletedLine = Object.assign({}, flow);
          }
        }
        const sourceNode = state.flows[deletedLine.id].source;
        const targetNode = state.flows[deletedLine.id].target;

        state.activities[sourceNode] && (state.activities[sourceNode].outgoing = '');
        state.activities[targetNode] && (state.activities[targetNode].incoming = '');
        state.start_event.id === sourceNode && (state.start_event.outgoing = '');
        state.end_event.id === sourceNode && (state.end_event.incoming = '');
        state.line = state.line.filter(ln => ln.id !== deletedLine.id);
        if (state.gateways[sourceNode]) {
          const gatewayNode = state.gateways[sourceNode];

          if (Array.isArray(gatewayNode.outgoing)) {
            gatewayNode.outgoing = gatewayNode.outgoing.filter(item => {
              return item !== deletedLine.id;
            });
            if (gatewayNode.type === ATOM_TYPE_DICT['branchgateway']) {
              const conditions = gatewayNode.conditions;

              conditions[deletedLine.id] && Vue.delete(conditions, deletedLine.id);
            }
          } else {
            gatewayNode.outgoing = '';
          }
        }
        if (state.gateways[targetNode]) {
          const gatewayNode = state.gateways[targetNode];

          if (Array.isArray(gatewayNode.incoming)) {
            gatewayNode.incoming = gatewayNode.incoming.filter(item => {
              return item !== deletedLine.id;
            });
          } else {
            gatewayNode.incoming = '';
          }
        }
        Vue.delete(state.flows, deletedLine.id);
      }
    },
        // 任务节点增加、删除、编辑操作，更新模板各相关字段数据
    setActivities (state, payload) {
      const {type, location} = payload;

      if (type === 'add') {
        if (!state.activities[location.id]) {
          if (location.type === 'tasknode') {
            state.activities[location.id] = {
              component: {
                code: location.atomId,
                data: location.data
              },
              error_ignorable: false,
              id: location.id,
              incoming: '',
              loop: null,
              name: location.name,
              optional: false,
              outgoing: '',
              stage_name: window.gettext('步骤1'),
              type: 'ServiceActivity',
              can_retry: true,
              isSkipped: true
            };
          } else if (location.type === 'subflow') {
            state.activities[location.id] = {
              constants: {},
              hooked_constants: [],
              id: location.id,
              incoming: '',
              loop: null,
              name: location.name,
              optional: false,
              outgoing: '',
              stage_name: window.gettext('步骤1'),
              template_id: location.atomId,
              version: location.atomVersion,
              type: 'SubProcess'
            };
          }
        }
      } else if (type === 'edit') {
        state.activities[location.id] = location;
        state.location.some(item => {
          if (item.id === location.id) {
            Vue.set(item, 'name', location.name);
            Vue.set(item, 'stage_name', location.stage_name);
          }
        });
      } else if (type === 'delete') {
        const {incoming, outgoing} = state.activities[location.id];
        const deletedlines = [incoming, outgoing];

        deletedlines.forEach(line => {
          const flow = state.flows[line];

          if (flow) {
            const targetNode = flow.target;
            const sourceNode = flow.source;

            state.activities[targetNode] && (state.activities[targetNode].incoming = '');
            state.activities[sourceNode] && (state.activities[sourceNode].outgoing = '');
            state.start_event.id === sourceNode && (state.start_event.outgoing = '');
            state.end_event.id === sourceNode && (state.end_event.incoming = '');
            state.line = state.line.filter(item => {
              return item.id !== line;
            });
            if (state.gateways[sourceNode]) {
              const gatewayNode = state.gateways[sourceNode];

              if (Array.isArray(gatewayNode.outgoing)) {
                gatewayNode.outgoing = gatewayNode.outgoing.filter(item => {
                  return item !== line;
                });
                if (gatewayNode.type === ATOM_TYPE_DICT['branchgateway']) {
                  const conditions = gatewayNode.conditions;

                  conditions[line] && Vue.delete(conditions, line);
                }
              } else {
                gatewayNode.outgoing = '';
              }
            }
            if (state.gateways[targetNode]) {
              const gatewayNode = state.gateways[targetNode];

              if (Array.isArray(gatewayNode.incoming)) {
                gatewayNode.incoming = gatewayNode.incoming.filter(item => {
                  return item !== line;
                });
              } else {
                gatewayNode.incoming = '';
              }
            }
            Vue.delete(state.flows, line);
          }
        });
        for (const cKey in state.constants) {
          const constant = state.constants[cKey];
          const sourceInfo = constant.source_info;

          if (sourceInfo && sourceInfo[location.id]) {
            if (Object.keys(sourceInfo).length > 1) {
              Vue.delete(sourceInfo, location.id);
            } else {
              Vue.delete(state.constants, constant.key);
            }
          }
        }
        Vue.delete(state.activities, location.id);
      }
    },
        // 网关节点增加、删除操作，更新模板各相关字段数据
    setGateways (state, payload) {
      const {type, location} = payload;

      if (type === 'add') {
        if (!state.gateways[location.id]) {
          state.gateways[location.id] = {
            id: location.id,
            incoming: location.type === 'convergegateway' ? [] : '',
            name: location.name,
            outgoing: location.type === 'convergegateway' ? '' : [],
            type: ATOM_TYPE_DICT[location.type]
          };
          if (location.type === 'branchgateway') {
            state.gateways[location.id].conditions = {};
          }
        }
      } else if (type === 'delete') {
        const {incoming, outgoing} = state.gateways[location.id];
        const deletedlines = Array.isArray(incoming) ? incoming.concat(outgoing) : outgoing.concat(incoming);

        deletedlines.forEach(line => {
          const flow = state.flows[line];

          if (flow) {
            const targetNode = flow.target;
            const sourceNode = flow.source;
            const targetGateway = state.gateways[targetNode];
            const sourceGateway = state.gateways[sourceNode];

            state.activities[targetNode] && (state.activities[targetNode].incoming = '');
            state.activities[sourceNode] && (state.activities[sourceNode].outgoing = '');
            state.start_event.id === sourceNode && (state.start_event.outgoing = '');
            state.end_event.id === sourceNode && (state.end_event.incoming = '');
            if (targetGateway && targetNode !== location.id) {
              if (typeof targetGateway.incoming === 'string') {
                targetGateway.incoming = '';
              } else {
                targetGateway.incoming = targetGateway.incoming.filter(item => {
                  return item !== line;
                });
              }
            }
            if (sourceGateway && sourceNode !== location.id) {
              if (typeof sourceGateway.outgoing === 'string') {
                sourceGateway.outgoing = '';
              } else {
                sourceGateway.outgoing = sourceGateway.outgoing.filter(item => {
                  return item !== line;
                });
              }
            }
            Vue.delete(state.flows, line);
          }
          state.line = state.line.filter(item => {
            return item.id !== line;
          });
        });
        Vue.delete(state.gateways, location.id);
      }
    },
        // 开始节点增加、删除操作，更新模板各相关字段数据
    setStartpoint (state, payload) {
      const {type, location} = payload;

      if (type === 'add') {
        if (!state.start_event.id) {
          state.start_event = {
            id: location.id,
            incoming: '',
            name: location.name,
            outgoing: '',
            type: 'EmptyStartEvent'
          };
        }
      } else if (type === 'delete') {
        let targetNode;
        let lineId;

        for (const item in state.flows) {
          if (state.flows[item].source === location.id) {
            targetNode = state.flows[item].target;
            lineId = state.flows[item].id;
          }
        }
        state.activities[targetNode] && (state.activities[targetNode].incoming = '');
        const gatewayNode = state.gateways[targetNode];

        if (gatewayNode) {
          if (typeof gatewayNode.incoming === 'string') {
            gatewayNode.incoming = '';
          } else {
            gatewayNode.incoming = gatewayNode.incoming.filter(item => item !== lineId);
          }
        }
        state.line = state.line.filter(item => {
          return item.id !== lineId;
        });
        Vue.delete(state.flows, lineId);
        Vue.set(state, 'start_event', {});
      }
    },
        // 终止节点增加、删除操作，更新模板各相关字段数据
    setEndpoint (state, payload) {
      const {type, location} = payload;

      if (type === 'add') {
        if (!state.end_event.id) {
          state.end_event = {
            id: location.id,
            incoming: '',
            name: location.name,
            outgoing: '',
            type: 'EmptyEndEvent'
          };
        }
      } else if (type === 'delete') {
        let sourceNode;
        let lineId;

        for (const item in state.flows) {
          if (state.flows[item].target === location.id) {
            sourceNode = state.flows[item].source;
            lineId = state.flows[item].id;
          }
        }
        state.activities[sourceNode] && (state.activities[sourceNode].outgoing = '');
        const gatewayNode = state.gateways[sourceNode];

        if (gatewayNode) {
          if (typeof gatewayNode.outgoing === 'string') {
            gatewayNode.outgoing = '';
          } else {
            gatewayNode.outgoing = gatewayNode.outgoing.filter(item => item !== lineId);
            if (gatewayNode.type === ATOM_TYPE_DICT['branchgateway']) {
              const conditions = gatewayNode.conditions;

              conditions[lineId] && Vue.delete(conditions, lineId);
            }
          }
        }
        state.line = state.line.filter(item => {
          return item.id !== lineId;
        });
        Vue.delete(state.flows, lineId);
        Vue.set(state, 'end_event', {});
      }
    },
        // 全局变量勾选是否为输出
    setOutputs (state, payload) {
      const {changeType, key} = payload;

      if (changeType === 'add') {
        state.outputs.push(key);
      } else {
        state.outputs = state.outputs.filter(item => {
          return item !== key;
        });
      }
    },
        // 修改state中的模板数据
    replaceTemplate (state, template) {
      if (template !== undefined) {
        for (const prop in template) {
          state[prop] = template[prop];
        }
      }
    },
        // 修改lines和locations
    replaceLineAndLocation (state, payload) {
            //  需要做一次深层拷贝
      const {lines, locations} = tools.deepClone(payload);

      state.line = lines;
      state.location = locations;
    }
  },
  actions: {
  },
  getters: {
        // 获取所有模板数据
    getLocalTemplateData (state) {
      return tools.deepClone(state);
    }
  }
};

export default template;
